#继承和多态
#1、继承
class Animal(object):
    def run(self):
        print("Animal is running...")
class Dog(Animal):
    def run(self ):
        print('DOG IS RUNNING')
    def eat(self):
        print('EATING Meat...')
class Cat(Animal):
    def run(self ):
        print('CAT IS RUNNING')
animal=Animal()
dog=Dog()
cat=Cat()
dog.run()
dog.eat()
cat.run()
#当子类和父类都存在相同的run()方法时，我们说，子类的run()覆盖了父类的run()，在代码运行的时候，总是会调用子类的run()。这样，我们就获得了继承的另一个好处：多态。

#判断一个变量是否是某个类型可以用isinstance()判断：
a=list()#a是list类型
print(isinstance(a,list))
#在继承关系中，如果一个实例的数据类型是某个子类，那它的数据类型也可以被看做是父类。但是，反过来就不行：
print(isinstance(dog,Dog))
print(isinstance(dog,Animal))
print(isinstance(animal,Dog))

def run_twice(animal):
    animal.run()
    animal.run()
run_twice(Animal())
run_twice(Dog())

class Tortoise(Animal):
    def run(self):
        print('Tortoise is running slowly')
run_twice(Tortoise())
#多态的好处就是，当我们需要传入Dog、Cat、Tortoise……时，我们只需要接收Animal类型就可以了，因为Dog、Cat、Tortoise……都是Animal类型，然后，按照Animal类型进行操作即可。由于Animal类型有run()方法，因此，传入的任意类型，只要是Animal类或者子类，就会自动调用实际类型的run()方法，这就是多态的意思：
'''对于一个变量，我们只需要知道它是Animal类型，无需确切地知道它的子类型，就可以放心地调用run()方法，
而具体调用的run()方法是作用在Animal、Dog、Cat还是Tortoise对象上，由运行时该对象的确切类型决定，这就是多态真正的威力：调用方法只管调用，不管细节，而当我们新增一种Animal的子类时，只要确保run()方法编写正确，不用管原来的代码是如何调用的。这就是著名的“开闭”原则：
对扩展开放：允许新增Animal子类；
对修改封闭：不需要修改依赖Animal类型的run_twice()等函数。'''
#小结：继承可以把父类的所有功能都直接拿过来，这样就不必重零做起，子类只需要新增自己特有的方法，也可以把父类不适合的方法覆盖重写。